const bcrypt = require("bcryptjs");

const nanoid = require("nanoid");

const { sequelize } = require("../../core/db");
const { Sequelize, Model } = require("sequelize");

// 定义用户模型
class User extends Model {
  static async verifyEmailPassword(email, plainPassword) {
    // 查询用户
    const user = await User.findOne({
      where: {
        email,
      },
    });

    if (!user) {
      throw new global.errs.AuthFailed("账号不存在");
    }

    // 验证密码
    const correct = bcrypt.compareSync(plainPassword, user.password);

    if (!correct) {
      throw new global.errs.AuthFailed("密码不正确");
    }

    return user;
  }

  // 查询是否存在 opendid 的小程序用户
  static async getUserByOpenid(openid) {
    // 查询用户
    const user = await User.findOne({
      where: {
        openid,
      },
    });
    if (user) {
      user.login_at = new Date();
      await user.save();
    }

    return user;
  }

  // 注册小程用户
  static async createUserByOpenid(openid) {
    // 查询用户
    const user = await User.create({
      openid,
      inviteCode: nanoid(10),
    });
    return user;
  }
}

// 初始用户模型
User.init(
  {
    uid: {
      type: Sequelize.INTEGER,
      primaryKey: true,
      autoIncrement: true,
    },
    eid: {
      type: Sequelize.INTEGER,
      comment: "身份证id",
    },
    user_name: {
      type: Sequelize.STRING,
      defaultValue: "微信用户",
    },

    point: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 0,
      comment: "积分",
    },
    status: {
      type: Sequelize.ENUM("active", "inactive", "banned"),
      allowNull: false,
      defaultValue: "active",
      comment: "用户状态",
    },
    phone: {
      type: Sequelize.STRING,
      defaultValue: "",
      comment: "",
    },

    inviteCode: {
      type: Sequelize.STRING,
    },
    power: {
      type: Sequelize.INTEGER,
      defaultValue: 1,
    },
    avatar: {
      type: Sequelize.STRING,
      defaultValue: "https://cdn.cellsplus.top/icon/def-avater.png",
    },
    pid: {
      type: Sequelize.INTEGER,
      comment: "邀请人",
    },
    login_at: {
      type: Sequelize.DATE,
      comment: "登录时间",
      defaultValue: new Date(),
    },

    cid: Sequelize.INTEGER,
    area: Sequelize.STRING,
    email: {
      type: Sequelize.STRING(128),
      unique: true,
    },

    password: {
      // 扩展 设计模式 观察者模式
      // ES6 Reflect Vue3.0
      type: Sequelize.STRING,
      set(val) {
        // 加密
        const salt = bcrypt.genSaltSync(10);
        // 生成加密密码
        const psw = bcrypt.hashSync(val, salt);
        this.setDataValue("password", psw);
      },
    },
    openid: {
      type: Sequelize.STRING(64),
      unique: true,
    },
  },
  {
    sequelize,
    tableName: "user",
  }
);

module.exports = {
  User,
};
